<?php

namespace app\index\controller;

use app\common\controller\Frontend;
use think\Db;

class Yunzhuo extends Frontend
{

    protected $noNeedLogin = '*';
    protected $noNeedRight = '*';
    private $sn = '';
    private $payTypeId = '';
    private $privateKey = '';
    private $publicKey = '';
    private $devId = '';
    private $keyStr = '';
    private $iv = '';

    public function post1($postData,$url)
    {
        $jsonData = json_encode($postData);
        // dump($url);die;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json'
        ));
        // 发送请求并获取响应
        $response = curl_exec($ch);

        return $response;
    }
    function third_order_id() {
        $timestamp = time(); // 当前时间戳
        $random = mt_rand(1000, 9999); // 生成一个 4 位随机数
        $orderNumber = $timestamp . $random; // 拼接时间戳和随机数
        return $orderNumber;
    }
    function generateOrderNumber() {
        $timestamp = time(); // 当前时间戳
        $random = mt_rand(1000, 9999); // 生成一个 4 位随机数

        $array1 = array(0,1,2,3,4,5,6,7,8,9,'q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m','Q','W','E','R','T','Y','U','I','O','P','M','N','B','V','C','X','Z','A','S','D','F','G','H','J','K','L');
        $i= 0;
        $str = null;
        while ( $i<= 21) {
            $str .= $array1[array_rand($array1,1)];
            $i++;

        }
        $orderNumber = $timestamp . $str; // 拼接时间戳和随机数
        return $orderNumber;
    }
    // 生成请求的签名
    public function generateSignature($apiKey, $data)
    {
        ksort($data); // 按键名进行升序排序

        $signData = '';
        foreach ($data as $key => $value) {
            $signData .= $key . '=' . $value . '&';
        }
        $signData .= 'key=' . $apiKey;

        return hash('MD5', $signData); // 使用HMAC-SHA256进行签名
    }
    //微信
    public function wx($res,$pay)
    {
        $config = json_decode($pay['json']);
        $this->sn = $config->sn;
        $this->payTypeId = $config->payTypeId;//支付方式0-自动判断、 1003微信、1004支付宝、1010银联扫码
        $privateKey = str_replace(" ", "<br>", $config->privateKey);
        $this->privateKey = '-----BEGIN RSA PRIVATE KEY-----'.
            '<br>'.$privateKey.
            '<br>'.'-----END RSA PRIVATE KEY-----';
        $this->publicKey = '-----BEGIN PUBLIC KEY-----'.
            '<br>'.$config->publicKey.
            '<br>'.'-----END PUBLIC KEY-----';
        $this->devId = $config->devId;
        $this->keyStr = $config->keyStr;
        $this->iv = $config->iv;
        //②、统一下单
        $dizhi = 'http://'.$this->request->host();
        $notifyUrl = $dizhi."/index/yunzhuo/wx_hd/id/".$res['id'].'/type/'.$res['type'].'/channel_id/'.$pay['id'];// 替换为您的支付回调通知地址
        // 构建统一下单请求参数
        $plainText = array(
            "sn"=>$this->sn,
            "payTypeId"=>$this->payTypeId,
            "outTradeId" => "yz".$this->third_order_id(), // 替换为您的订单号
            "tradeAmount"=>strval($res['main_free']*100),
            "notifyUrl" => $notifyUrl,
        );
        $content = $this->aes128cbcEncrypt(json_encode($plainText), $this->iv, $this->keyStr);

        $data = array(
            'devId'     => $this->devId,
            'content'   => $content,
            'signature' => $this->signData($this->privateKey, $content),
        );
        $url = 'https://api.plutuspay.com/open/v2/preCreate';
        $result = $this->post1($data,$url);
        /* AES CBC Pkcs7 decrypt */
        $temp = json_decode($result, 1);
        $content = $temp['content'];
        $sign = $temp['signature'];
        $string = json_encode(array('content'=>$content, 'signature'=>$sign));
        $returnV = $this->verifySign($this->publicKey, $content, $sign);
        $return = $this->aes128cbcDecrypt($content, $this->keyStr, $this->iv);
        $return = json_decode($return, 1);
        if (!$result || $return['status'] != '00') {  //失败处理
            dump($result['resp_msg']);die;
        } else {    //成功处理
            $jsApiParameters = $return['qrCode'];
            return $jsApiParameters;

        }
    }
    function addPkcs7Padding($string, $blocksize = 16) {
        $len = strlen($string);
        $pad = $blocksize - ($len % $blocksize);
        $string .= str_repeat(chr($pad), $pad);
        return $string;
    }
    function aes128cbcEncrypt($string, $iv, $key) {
        return base64_encode(openssl_encrypt($this->addPkcs7Padding($string),'AES-128-CBC', hex2bin($key),0, hex2bin($iv)));
    }
    function aes128cbcOpensslEncrypt($string, $iv, $key) {
        return openssl_encrypt($string,'AES-128-CBC', hex2bin($key), 0, hex2bin($iv));
    }

    function stripPkcs7Padding($text) {
        $pad = ord($text[strlen($text) - 1]);
        if ($pad > strlen($text)) return false;
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
        return substr($text, 0, -1 * $pad);
    }
    function aes128cbcDecrypt($string, $key, $iv) {
        return $this->stripPkcs7Padding(openssl_encrypt(base64_decode($string),'AES-128-CBC', hex2bin($key),  0, hex2bin($iv)));
    }
    function aes128cbcOpensslDecrypt($string, $key, $iv) {
        return openssl_decrypt($string, 'AES-128-CBC', hex2bin($key), 0, hex2bin($iv));
    }

    function signData($privateKey, $data) {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign(base64_decode($data), $binary_signature, $privateKey, $algo);
        return base64_encode($binary_signature);
    }

    function verifySign($publicKey, $content, $sign) {
        return (bool)openssl_verify(base64_decode($content), base64_decode($sign), $publicKey, 'SHA256');
    }
    //微信异步通知
    public function wx_hd()
    {
        $xml_data = file_get_contents('php://input');
        $params = request()->param();
        $channel_id = $params['channel_id'];
        $temp = json_decode($xml_data, 1);
        $content = $temp['content'];
        $sign = $temp['signature'];
        $pay = Db::name('pay_channel')->where('id',$channel_id)->find();
        $config = json_decode($pay['json']);
        $this->sn = $config->sn;
        $this->payTypeId = $config->payTypeId;//支付方式0-自动判断、 1003微信、1004支付宝、1010银联扫码
        $privateKey = str_replace(" ", "\n", $config->privateKey);
        $this->privateKey = '-----BEGIN RSA PRIVATE KEY-----'.
            '<br>'.$privateKey.
            '<br>'.'-----END RSA PRIVATE KEY-----';
        $this->publicKey = '-----BEGIN PUBLIC KEY-----'.
            '<br>'.$config->publicKey.
            '<br>'.'-----END PUBLIC KEY-----';
        $this->devId = $config->devId;
        $this->keyStr = $config->keyStr;
        $this->iv = $config->iv;
        $string = json_encode(array('content'=>$content, 'signature'=>$sign));
        $returnV = $this->verifySign($this->publicKey, $content, $sign);
        $return = $this->aes128cbcDecrypt($content,$this->keyStr, $this->iv);
        $return = json_decode($return, 1);
        $filename = "example.txt";
        Db::startTrans();
        try{
            //修改数据
            $up = Db::name('list_one')
                ->where(['id'=>$params['id']])
                ->update([
                    'jiaofei'=>2,
                    'jiaofei_price'=>$return['tradeAmount'],
                    'trade_no'=>$return['outTransId'],
                    'out_trade_no'=>$return['tradeId'],
                    'jiaofei_time'=>date("Y-m-d H:i:s",time()),
                    'feiyong_type'=>$params['type'],
                    'type'=>$params['type']
                ]);

            $model = new Index();
            $sid = $model->num($params['id'],$channel_id);
            // 提交事务
            Db::commit();
            return 'SUCCESS';
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $c = $e->getMessage();
            db('ceshi')->insert(['text'=>'111'.date("Y-m-d H:i:s",time()).$c]);
            $returnData = [
                "code" => "ERROR",
                "message" => "回调失败"
            ];
        }
    }
}